package main

import (
	"arbitrage/persistence"
	"context"
	"errors"
	"sort"
	"strconv"
	"strings"
	"sync"
	"time"

	"gitee.com/hacker61/go-binance/v2"
	"gitee.com/hacker61/go-binance/v2/futures"
)

var (
	binanceBookTickerC        chan *binance.WsBookTickerEvent
	futuresBookTickerC        chan *futures.WsBookTickerEvent
	symbolBookTickers         SymbolBookTickerSlice
	canCreateSymbolBookTicker SymbolBookTicker
)

var (
	limitOrderTimer            *time.Timer
	binanceLimitOrderId        int64            //现货限价单OrderId
	futuresLimitOrderId        int64            //合约限价单OrderId
	limitOrderSymbolBookTicker SymbolBookTicker //当前已经开的限价单对应的symbol行情信息
	bWaitLimitOrder            bool             //是否处于限价单已开，但还没确定是否成交阶段

	// 限价单单腿成交后，立刻针对这条腿，下平单的限价单
	binanceAntiLimitOrderId  int64   //现货单平单限价单OrderId
	futuresAntiLimitOrderId  int64   //合约单平单限价单OrderId
	subStateBinanceExecQty   float64 //子状态变更时存下的记录
	subStateBinanceExecPrice float64 //子状态变更时存下的记录
	subStateFuturesExecQty   float64 //子状态变更时存下的记录
	subStateFuturesExecPrice float64 //子状态变更时存下的记录
	//pBinanceFilledOrder      *binance.WsExecutionReportEvent // 现货单成交记录
	//pFuturesOrderTradeUpdate *futures.WsOrderTradeUpdate     // 合约单成交记录

	chanBinanceFilledOrder      chan binance.WsExecutionReportEvent
	chanFuturesOrderTradeUpdate chan futures.WsOrderTradeUpdate
)

var (
	stateMachine *StateMachine
)

func main_v2_init() {
	binanceBookTickerC = make(chan *binance.WsBookTickerEvent, 1)
	futuresBookTickerC = make(chan *futures.WsBookTickerEvent, 1)
	symbolBookTickers = make(SymbolBookTickerSlice, 0)

	chanBinanceFilledOrder = make(chan binance.WsExecutionReportEvent, 1)
	chanFuturesOrderTradeUpdate = make(chan futures.WsOrderTradeUpdate, 1)

	//bWaitLimitOrder = false

	if stateMachine == nil {
		stateMachine = NewStateMachine()
		symbol, spotCount, futureCount, spotPrice, futurePrice, err := ppersistence.QueryArbitragePosition()
		if err != nil {
			//bPosition = false
			err = stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		} else {
			//bPosition = true
			sp := persistence.ArbitragePosition{Symbol: symbol, SpotCount: spotCount, FutureCount: futureCount, SpotPrice: spotPrice, FuturePrice: futurePrice}
			err = stateMachine.ChangeState(State_Position, sp)
			if err != nil {
				Error.Println(err)
			}
		}
	}
}

func processWithCurBookTicker() {
	for {
		var bCanCreateChanged = false
		// 引入状态机后的逻辑
		// 首先处理从websocket到来的数据
		if stateMachine.State == State_NotPosition || stateMachine.State == State_OneCanCreatePosition || stateMachine.State == State_LimitOrderCreated {
			var binanceBookTicker *binance.WsBookTickerEvent
			var futuresBookTicker *futures.WsBookTickerEvent
			select {
			case binanceBookTicker = <-binanceBookTickerC:
				//Info.Printf("binance book ticker: %v\n", binanceBookTicker)
				index := symbolBookTickers.SymbolIndex(binanceBookTicker.Symbol)
				if index == -1 {
					symbolBookTicker := SymbolBookTicker{Symbol: binanceBookTicker.Symbol, BinanceBookTicker: binanceBookTicker, Premium: -1}
					symbolBookTickers = append(symbolBookTickers, symbolBookTicker)
				} else {
					symbolBookTickers[index].BinanceBookTicker = binanceBookTicker
					symbolBookTickers[index].CalcPremium()
					if symbolBookTickers[index].Premium > 0 { // index对应的交易对的溢价率大于0时才重排
						sort.Sort(sort.Reverse(symbolBookTickers))
					}
					//Debug.Printf("Symbol: %s, BinanceBookTicker: %v, FuturesBookTicker: %v, Premium: %v\n", symbolBookTickers[index].Symbol, symbolBookTickers[index].BinanceBookTicker, symbolBookTickers[index].FuturesBookTicker, symbolBookTickers[index].Premium)
					//sort.Sort(sort.Reverse(symbolBookTickers))
				}
				if (stateMachine.State == State_OneCanCreatePosition || stateMachine.State == State_LimitOrderCreated) && canCreateSymbolBookTicker.Symbol == binanceBookTicker.Symbol {
					canCreateSymbolBookTicker.BinanceBookTicker = binanceBookTicker
					canCreateSymbolBookTicker.CalcPremium()
					bCanCreateChanged = true
				}
			case futuresBookTicker = <-futuresBookTickerC:
				//Info.Printf("futures book ticker: %v\n", futuresBookTicker)
				index := symbolBookTickers.SymbolIndex(futuresBookTicker.Symbol)
				if index == -1 {
					symbolBookTicker := SymbolBookTicker{Symbol: futuresBookTicker.Symbol, FuturesBookTicker: futuresBookTicker, Premium: -1}
					symbolBookTickers = append(symbolBookTickers, symbolBookTicker)
				} else {
					symbolBookTickers[index].FuturesBookTicker = futuresBookTicker
					symbolBookTickers[index].CalcPremium()
					if symbolBookTickers[index].Premium > 0 { // index对应的交易对的溢价率大于0时才重排
						sort.Sort(sort.Reverse(symbolBookTickers))
					}
					//Debug.Printf("Symbol: %s, BinanceBookTicker: %v, FuturesBookTicker: %v, Premium: %v\n", symbolBookTickers[index].Symbol, symbolBookTickers[index].BinanceBookTicker, symbolBookTickers[index].FuturesBookTicker, symbolBookTickers[index].Premium)
					//sort.Sort(sort.Reverse(symbolBookTickers))
				}
				if (stateMachine.State == State_OneCanCreatePosition || stateMachine.State == State_LimitOrderCreated) && canCreateSymbolBookTicker.Symbol == futuresBookTicker.Symbol {
					canCreateSymbolBookTicker.FuturesBookTicker = futuresBookTicker
					canCreateSymbolBookTicker.CalcPremium()
					bCanCreateChanged = true
				}
			}
		} else if stateMachine.State == State_Position || stateMachine.State == State_OneCanClosePosition || stateMachine.State == State_AntiLimitOrderCreated {
			var binanceBookTicker *binance.WsBookTickerEvent
			var futuresBookTicker *futures.WsBookTickerEvent
			select {
			case binanceBookTicker = <-binanceBookTickerC:
				if binanceBookTicker.Symbol == symbolPosition.Symbol {
					canCreateSymbolBookTicker.BinanceBookTicker = binanceBookTicker
					canCreateSymbolBookTicker.CalcPremium()
					if canCreateSymbolBookTicker.FuturesBookTicker != nil {
						bCanCreateChanged = true
					}
				}
			case futuresBookTicker = <-futuresBookTickerC:
				if futuresBookTicker.Symbol == symbolPosition.Symbol {
					canCreateSymbolBookTicker.FuturesBookTicker = futuresBookTicker
					canCreateSymbolBookTicker.CalcPremium()
					if canCreateSymbolBookTicker.BinanceBookTicker != nil {
						bCanCreateChanged = true
					}
				}
			}
		}

		// 根据不同的状态进行相应处理
		if stateMachine.State == State_NotPosition {
			if len(symbolBookTickers) > 0 && symbolBookTickers[0].Premium > conf.CreatePremium {
				symbolExchangeInfo, bOk := symbolExchangeInfos[symbolBookTickers[0].Symbol]
				if bOk {
					dPremiumStage = float64(int((symbolBookTickers[0].Premium-conf.CreatePremium)/conf.PremiumStage))*conf.PremiumStage + conf.CreatePremium
					Info.Printf("symbolBookTickers[0] = %v, dPremiumStage = %v, exchangeInfo = %v\n", symbolBookTickers[0], dPremiumStage, symbolExchangeInfo)

					err := stateMachine.ChangeState(State_OneCanCreatePosition, symbolBookTickers[0])
					if err != nil {
						Error.Println(err)
					}
				} else {
					Error.Printf("Symbol %v has no exchangeInfo\n", symbolBookTickers[0].Symbol)
				}
			}
		} else if stateMachine.State == State_OneCanCreatePosition {
			if bCanCreateChanged {
				if canCreateSymbolBookTicker.Premium > dPremiumStage && canCreateSymbolBookTicker.Premium < conf.GreatCreatePremium {
					dPremiumStage = float64(int((canCreateSymbolBookTicker.Premium-conf.CreatePremium)/conf.PremiumStage))*conf.PremiumStage + conf.CreatePremium
					Info.Printf("canCreateSymbolBookTicker = %v, dPremiumStage = %v\n", canCreateSymbolBookTicker, dPremiumStage)
				} else if canCreateSymbolBookTicker.Premium < conf.CreatePremium {
					if symbolBookTickers[0].Premium > conf.CreatePremium {
						//sOneCanCreatePosition = symbolBookTickers[0].Symbol
						//bOneCanCreatePosition = true
						dPremiumStage = float64(int((symbolBookTickers[0].Premium-conf.CreatePremium)/conf.PremiumStage))*conf.PremiumStage + conf.CreatePremium
						Info.Printf("symbolBookTickers[0] = %v, dPremiumStage = %v\n", symbolBookTickers[0], dPremiumStage)
						//canCreateSymbolBookTicker = symbolBookTickers[0]

						err := stateMachine.ChangeState(State_OneCanCreatePosition, symbolBookTickers[0])
						if err != nil {
							Error.Println(err)
						}
					} else {
						//sOneCanCreatePosition = ""
						//bOneCanCreatePosition = false
						dPremiumStage = 0.0
						Info.Printf("bOneCanCreatePosition stop, symbolBookTickers[0] = %v\n", symbolBookTickers[0])

						err := stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					}
				} else {
					// 挂单量较大时，可以考虑直接下市价单
					/*
						futuresBestBidPrice, err := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, 64)
						if err != nil {
							Error.Printf("FuturesBookTicker.BestBidPrice is not Float64, err = %v\n", err)
							return
						}
						futuresBestBidQty, err := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestBidQty, 64)
						if err != nil {
							Error.Printf("FuturesBookTicker.BestBidQty is not Float64, err = %v\n", err)
							return
						}
						binanceBestAskPrice, err := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestAskPrice, 64)
						if err != nil {
							Error.Printf("BinanceBookTicker.BestAskPrice is not Float64, err = %v\n", err)
							return
						}
						binanceBestAskQty, err := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestAskQty, 64)
						if err != nil {
							Error.Printf("BinanceBookTicker.BestAskQty is not Float64, err = %v\n", err)
							return
						}
						if futuresBestBidPrice*futuresBestBidQty > conf.QuoteMultiple*conf.QuoteOrderQty &&
							binanceBestAskPrice*binanceBestAskQty > conf.QuoteMultiple*conf.QuoteOrderQty {
							Info.Printf("Create Arbitrage Order, canCreateSymbolBookTicker %v, canCreateSymbolBookTicker.BinanceBookTicker %v, canCreateSymbolBookTicker.FuturesBookTicker %v",
								canCreateSymbolBookTicker, *(canCreateSymbolBookTicker.BinanceBookTicker), *(canCreateSymbolBookTicker.FuturesBookTicker))
							// 此种情况下，直接下发市价单
							createArbitrageOrder_v2(conf.QuoteOrderQty, canCreateSymbolBookTicker.BinanceBookTicker.BestAskPrice, canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, canCreateSymbolBookTicker.Symbol)
							symbol, spotCount, futureCount, spotPrice, futurePrice, err := ppersistence.QueryArbitragePosition()

							sp := persistence.ArbitragePosition{Symbol: symbol, SpotCount: spotCount, FutureCount: futureCount, SpotPrice: spotPrice, FuturePrice: futurePrice}
							err = stateMachine.ChangeState(State_Position, sp)
							if err != nil {
								Error.Println(err)
							}
							panic(err) // 测试
						} else {
							dPremiumStage = 0.0
							Info.Printf("bOneCanCreatePosition stop, symbolBookTickers[0] = %v\n", symbolBookTickers[0])

							err := stateMachine.ChangeState(State_NotPosition)
							if err != nil {
								Error.Println(err)
							}
						}
					*/
					// 暂时关闭，一会打开

					if symbolBookTickers[0].Symbol == canCreateSymbolBookTicker.Symbol {
						Info.Printf("Create Arbitrage Order, canCreateSymbolBookTicker %v, canCreateSymbolBookTicker.BinanceBookTicker %v, canCreateSymbolBookTicker.FuturesBookTicker %v",
							canCreateSymbolBookTicker, *(canCreateSymbolBookTicker.BinanceBookTicker), *(canCreateSymbolBookTicker.FuturesBookTicker))
						//createArbitrageOrder_v2(conf.QuoteOrderQty, canCreateSymbolBookTicker.BinanceBookTicker.BestAskPrice, canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, canCreateSymbolBookTicker.Symbol)
						binanceOrderId, futuresOrderId, binanceErr, futuresErr := createArbitrageLimitOrder(conf.QuoteOrderQty,
							canCreateSymbolBookTicker.BinanceBookTicker.BestAskPrice, canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, canCreateSymbolBookTicker.Symbol)
						if binanceErr == nil && futuresErr == nil {
							//bWaitLimitOrder = true
							if limitOrderTimer == nil {
								limitOrderTimer = time.NewTimer(5 * time.Second)
							} else {
								select {
								case <-limitOrderTimer.C:
									limitOrderTimer.Reset(5 * time.Second)
								default:
									limitOrderTimer.Reset(5 * time.Second)
								}
							}
							//binanceLimitOrderId = binanceOrderId
							//futuresLimitOrderId = futuresOrderId
							//limitOrderSymbolBookTicker = canCreateSymbolBookTicker

							// 将当前溢价保存起来
							dPremiumStage = canCreateSymbolBookTicker.Premium

							err := stateMachine.ChangeState(State_LimitOrderCreated, binanceOrderId, futuresOrderId)
							if err != nil {
								Error.Println(err)
							}
						}
					} else {
						//sOneCanCreatePosition = symbolBookTickers[0].Symbol
						//bOneCanCreatePosition = true
						dPremiumStage = float64(int((symbolBookTickers[0].Premium-conf.CreatePremium)/conf.PremiumStage))*conf.PremiumStage + conf.CreatePremium
						Info.Printf("symbolBookTickers[0] = %v, dPremiumStage = %v\n", symbolBookTickers[0], dPremiumStage)
						//canCreateSymbolBookTicker = symbolBookTickers[0]

						err := stateMachine.ChangeState(State_OneCanCreatePosition, symbolBookTickers[0])
						if err != nil {
							Error.Println(err)
						}
					}

				}
			}
		} else if stateMachine.State == State_LimitOrderCreated {
			var tmpBinanceFilledOrder binance.WsExecutionReportEvent
			var tmpFuturesUserData futures.WsOrderTradeUpdate
			select {
			case <-limitOrderTimer.C:
				timeout_NotPosition()
				// 将逻辑单独提出来
				/*
					_, binanceExecQty, binanceExecPrice, binanceStatus, binanceErr := getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
					_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr := getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
					if binanceErr == nil && futuresErr == nil {
						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					} else if binanceErr == nil {
						// 取消当前合约限价单
						if futuresStatus == futures.OrderStatusTypeNew {
							err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
							if err != nil {
								Error.Println(err)
							}
						}
						// 当前限价状态为现货反向单下单成功，取消现货反向单
						if stateMachine.SubState == SubState_BinanceAntiCreated {
							if binanceAntiLimitOrderId != 0 {
								err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
								if err != nil {
									Error.Println(err)
								}
							}
						}
						futuresBestBidPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, 64)
						if (futuresBestBidPrice-binanceExecPrice)/binanceExecPrice > conf.CreatePremium {
							var err error
							_, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder(canCreateSymbolBookTicker.Symbol, futuresBestBidPrice, conf.QuoteOrderQty)
							if err != nil {
								err = createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
								if err != nil {
									Error.Println(err)
								}

								err = stateMachine.ChangeState(State_NotPosition)
								if err != nil {
									Error.Println(err)
								}
							} else {
								// 状态改为持仓
								changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
							}
						} else {
							err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
							if err != nil {
								Error.Println(err)
							}

							err = stateMachine.ChangeState(State_NotPosition)
							if err != nil {
								Error.Println(err)
							}
						}
					} else if futuresErr == nil {
						// 取消当前的现货限价单
						if binanceStatus == binance.OrderStatusTypeNew {
							err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
							if err != nil {
								Error.Println(err)
							}
						}
						// 如果限价状态是合约反向单已下发，此时需要取消该反向单
						if stateMachine.SubState == SubState_FuturesAntiCreated {
							if futuresAntiLimitOrderId != 0 {
								err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
								if err != nil {
									Error.Println(err)
								}
							}
						}
						binanceBestAskPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestAskPrice, 64)
						if (futuresExecPrice-binanceBestAskPrice)/binanceBestAskPrice > conf.CreatePremium {
							var err error
							_, binanceExecQty, binanceExecPrice, err = createBinanceBuyOrder(canCreateSymbolBookTicker.Symbol, conf.QuoteOrderQty)
							if err != nil {
								err = createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
								if err != nil {
									Error.Println(err)
								}

								err = stateMachine.ChangeState(State_NotPosition)
								if err != nil {
									Error.Println(err)
								}
							} else {
								// 状态改为持仓
								changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
							}
						} else {
							err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
							if err != nil {
								Error.Println(err)
							}

							err = stateMachine.ChangeState(State_NotPosition)
							if err != nil {
								Error.Println(err)
							}
						}
					} else {
						if binanceStatus == binance.OrderStatusTypeNew {
							err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
							if err != nil {
								Error.Println(err)
							}
						}
						if futuresStatus == futures.OrderStatusTypeNew {
							err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
							if err != nil {
								Error.Println(err)
							}
						}

						err := stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					}
				*/
			case tmpBinanceFilledOrder = <-chanBinanceFilledOrder:
				// 某个现货单成交，此时
				// 1. 合约单未成交，现货单未成交，查询是否是现货单成交，如果是，创建一个现货反向单，价格为当前成交现货价格 * (1+ conf.CreatePremium)
				// 2. 合约单未成交，现货单已成交，查询是否是现货反向单成交，如果是，取消合约单
				// 3. 合约单已成交，查询是否是现货单成交，如果是，将合约单成交时创建的合约反向单取消
				if stateMachine.SubState == SubState_Init {
					subProcess_BinanceFilled_NotPosition_InitSubState(tmpBinanceFilledOrder)
				} else if stateMachine.SubState == SubState_BinanceAntiCreated {
					subProcess_BinanceFilled_NotPosition_BinanceAntiCreatedSubState()
				} else if stateMachine.SubState == SubState_FuturesAntiCreated {
					subProcess_BinanceFilled_NotPosition_FuturesAntiCreatedSubState(tmpBinanceFilledOrder)
				} else {
					Warning.Printf("SubState is %v\n", stateMachine.SubState)
				}
			case tmpFuturesUserData = <-chanFuturesOrderTradeUpdate:
				// 某个合约单成交，此时
				// 1. 现货单未成交，合约单单未成交，查询是否是合约单成交，如果是，创建一个合约反向单，价格为当前成交合约价格 * (1- conf.CreatePremium)
				// 2. 现货单未成交，合约单已成交，查询是否是合约反向单成交，如果是，取消现货单
				// 3. 现货单已成交，查询是否是合约单成交，如果是，将现货单成交时创建的现货反向单取消
				if stateMachine.SubState == SubState_Init {
					subProcess_FuturesFilled_NotPosition_InitSubState(tmpFuturesUserData)
				} else if stateMachine.SubState == SubState_FuturesAntiCreated {
					subProcess_FuturesFilled_NotPosition_FuturesAntiCreatedSubState(tmpFuturesUserData)
				} else if stateMachine.SubState == SubState_BinanceAntiCreated {
					subProcess_FuturesFilled_NotPosition_BinanceAntiCreatedSubState(tmpFuturesUserData)
				} else {
					Warning.Printf("SubState is %v\n", stateMachine.SubState)
				}
			default:
				if bCanCreateChanged {
					Info.Println(canCreateSymbolBookTicker)
				}
			}
		} else if stateMachine.State == State_Position {
			if bCanCreateChanged {
				if canCreateSymbolBookTicker.AntiPremium < conf.ClosePremium {
					dPremiumStage = float64(int((canCreateSymbolBookTicker.AntiPremium-conf.ClosePremium)/conf.PremiumStage))*conf.PremiumStage + conf.ClosePremium
					Info.Printf("canCreateSymbolBookTicker.Premium = %v, dPremiumStage = %v\n", canCreateSymbolBookTicker.AntiPremium, dPremiumStage)

					err := stateMachine.ChangeState(State_OneCanClosePosition)
					if err != nil {
						Error.Println(err)
					}
				}
			}
		} else if stateMachine.State == State_OneCanClosePosition {
			if bCanCreateChanged {
				if canCreateSymbolBookTicker.AntiPremium < dPremiumStage && canCreateSymbolBookTicker.AntiPremium > conf.GreatClosePremium {
					dPremiumStage = float64(int((canCreateSymbolBookTicker.AntiPremium-conf.ClosePremium)/conf.PremiumStage))*conf.PremiumStage + conf.ClosePremium
					Info.Printf("canCreateSymbolBookTicker.AntiPremium = %v, dPremiumStage = %v\n", canCreateSymbolBookTicker.AntiPremium, dPremiumStage)

					//err := stateMachine.ChangeState(State_OneCanClosePosition)
					//if err != nil {
					//	Error.Println(err)
					//}
				} else if canCreateSymbolBookTicker.AntiPremium > conf.ClosePremium {
					err := stateMachine.ChangeState(State_Position, symbolPosition)
					if err != nil {
						Error.Println(err)
					}
				} else {
					Info.Printf("Close Arbitrage Order, canCreateSymbolBookTicker %v, canCreateSymbolBookTicker.BinanceBookTicker %v, canCreateSymbolBookTicker.FuturesBookTicker %v",
						canCreateSymbolBookTicker, *(canCreateSymbolBookTicker.BinanceBookTicker), *(canCreateSymbolBookTicker.FuturesBookTicker))
					// 达到平仓条件，平仓
					//closeArbitrageOrder(symbolPosition.SpotCount, symbolPosition.FutureCount, symbolPosition.Symbol)
					//bPosition = false
					//panic(errors.New("close Arbitrage Order"))
					binanceOrderId, futuresOrderId, binanceErr, futuresErr := closeArbitrageLimitOrder(symbolPosition.SpotCount,
						symbolPosition.FutureCount, canCreateSymbolBookTicker.BinanceBookTicker.BestBidPrice, canCreateSymbolBookTicker.FuturesBookTicker.BestAskPrice, symbolPosition.Symbol)
					if binanceErr == nil && futuresErr == nil {
						if limitOrderTimer == nil {
							limitOrderTimer = time.NewTimer(5 * time.Second)
						} else {
							select {
							case <-limitOrderTimer.C:
								limitOrderTimer.Reset(5 * time.Second)
							default:
								limitOrderTimer.Reset(5 * time.Second)
							}
						}

						err := stateMachine.ChangeState(State_AntiLimitOrderCreated, binanceOrderId, futuresOrderId)
						if err != nil {
							Error.Println(err)
						}
					}
				}
			}
		} else if stateMachine.State == State_AntiLimitOrderCreated {
			var tmpBinanceFilledOrder binance.WsExecutionReportEvent
			var tmpFuturesUserData futures.WsOrderTradeUpdate
			select {
			case <-limitOrderTimer.C:
				//Info.Println(stateMachine.SubState, binanceAntiLimitOrderId, futuresAntiLimitOrderId, pBinanceFilledOrder, pFuturesOrderTradeUpdate)
				Info.Println(stateMachine.SubState, binanceAntiLimitOrderId, futuresAntiLimitOrderId)
				_, _, binanceExecPrice, binanceStatus, binanceErr := getBinanceOrderInf(symbolPosition.Symbol, binanceLimitOrderId)
				_, _, futuresExecPrice, futuresStatus, futuresErr := getFuturesOrderInf(symbolPosition.Symbol, futuresLimitOrderId)
				if binanceErr == nil && futuresErr == nil {
					err := ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
					if err != nil {
						Error.Println(err)
						panic(err)
					}

					err = stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
					panic(err)
				} else if binanceErr == nil {
					// 取消当前合约限价单
					if futuresStatus == futures.OrderStatusTypeNew {
						err := cancelFuturesLimitOrder(symbolPosition.Symbol, futuresLimitOrderId)
						if err != nil {
							Error.Println(err)
						}
					}
					// 当前限价状态为现货反向单下单成功，取消现货反向单
					if stateMachine.SubState == SubState_BinanceAntiCreated {
						if binanceAntiLimitOrderId != 0 {
							err := cancelBinanceLimitOrder(symbolPosition.Symbol, binanceAntiLimitOrderId)
							if err != nil {
								Error.Println(err)
							}
						}
					}
					futuresBestAskPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestAskPrice, 64)
					if (futuresBestAskPrice-binanceExecPrice)/binanceExecPrice < conf.ClosePremium {
						var err error
						err = createFuturesBuyOrder(symbolPosition.Symbol, symbolPosition.FutureCount)
						if err != nil {
							Error.Println(err)
							panic(err)
						} else {
							err := ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
							if err != nil {
								Error.Println(err)
								panic(err)
							}

							err = stateMachine.ChangeState(State_NotPosition)
							if err != nil {
								Error.Println(err)
							}
							panic(err)
						}
					} else {
						var err error
						err = createFuturesBuyOrder(symbolPosition.Symbol, symbolPosition.FutureCount)
						if err != nil {
							Error.Println(err)
							panic(err)
						} else {
							err := ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
							if err != nil {
								Error.Println(err)
								panic(err)
							}

							err = stateMachine.ChangeState(State_NotPosition)
							if err != nil {
								Error.Println(err)
							}
							panic(err)
						}
					}
				} else if futuresErr == nil {
					// 取消当前的现货限价单
					if binanceStatus == binance.OrderStatusTypeNew {
						err := cancelBinanceLimitOrder(symbolPosition.Symbol, binanceLimitOrderId)
						if err != nil {
							Error.Println(err)
						}
					}
					// 如果限价状态是合约反向单已下发，此时需要取消该反向单
					if stateMachine.SubState == SubState_FuturesAntiCreated {
						if futuresAntiLimitOrderId != 0 {
							err := cancelFuturesLimitOrder(symbolPosition.Symbol, futuresAntiLimitOrderId)
							if err != nil {
								Error.Println(err)
							}
						}
					}
					binanceBestBidPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestBidPrice, 64)
					if (futuresExecPrice-binanceBestBidPrice)/binanceBestBidPrice < conf.ClosePremium {
						var err error
						err = createBinanceSellOrder(symbolPosition.Symbol, symbolPosition.SpotCount)
						if err != nil {
							Error.Println(err)
							panic(err)
						} else {
							err := ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
							if err != nil {
								Error.Println(err)
								panic(err)
							}

							err = stateMachine.ChangeState(State_NotPosition)
							if err != nil {
								Error.Println(err)
							}
							panic(err)
						}
					} else {
						var err error
						err = createBinanceSellOrder(symbolPosition.Symbol, symbolPosition.SpotCount)
						if err != nil {
							Error.Println(err)
							panic(err)
						} else {
							err := ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
							if err != nil {
								Error.Println(err)
								panic(err)
							}

							err = stateMachine.ChangeState(State_NotPosition)
							if err != nil {
								Error.Println(err)
							}
							panic(err)
						}
					}
				} else {
					if binanceStatus == binance.OrderStatusTypeNew {
						err := cancelBinanceLimitOrder(symbolPosition.Symbol, binanceLimitOrderId)
						if err != nil {
							Error.Println(err)
						}
					}
					if futuresStatus == futures.OrderStatusTypeNew {
						err := cancelFuturesLimitOrder(symbolPosition.Symbol, futuresLimitOrderId)
						if err != nil {
							Error.Println(err)
						}
					}

					err := stateMachine.ChangeState(State_Position, symbolPosition)
					if err != nil {
						Error.Println(err)
					}
				}
			case tmpBinanceFilledOrder = <-chanBinanceFilledOrder:
				// 有现货单成交，此时
				// 1. 当前现货和合约都没成交，判断现货单是否成交，如果成交，下现货反向单，价格为现货成交价格*(1-conf.CreatePremium)
				// 2. 当前现货单已成交，并且已下发现货反向单，判断现货反向单是否成交，如果成交，取消合约单，更新数据库
				// 3. 当前合约单已成交，并且已下发合约反向单，判断现货单是否成交，如果成交，取消合约反向单，当前状态改为未持仓
				if stateMachine.SubState == SubState_Init {
					subProcess_BinanceFilled_Position_InitSubState(tmpBinanceFilledOrder)
				} else if stateMachine.SubState == SubState_BinanceAntiCreated {
					subProcess_BinanceFilled_Position_BinanceAntiCreatedSubState(tmpBinanceFilledOrder)
				} else if stateMachine.SubState == SubState_FuturesAntiCreated {
					subProcess_BinanceFilled_Position_FuturesAntiCreatedSubState(tmpBinanceFilledOrder)
				} else {
					Error.Printf("Unknown SubState %v\n", stateMachine.SubState)
				}
			case tmpFuturesUserData = <-chanFuturesOrderTradeUpdate:
				// 有合约单成交，此时
				// 1. 当前现货和合约都没成交，判断合约单是否成交，如果成交，下合约反向单，价格为合约成交价格*(1+conf.CreatePremium)
				// 2. 当前合约单已成交，并且已下发合约反向单，判断合约反向单是否成交，如果成交，取消现货单，更新数据库
				// 3. 当前现货单已成交，并且已下发现货反向单，判断合约单是否成交，如果成交，取消现货反向单，当前状态改为未持仓
				if stateMachine.SubState == SubState_Init {
					subProcess_FuturesFilled_Position_InitSubState(tmpFuturesUserData)
				} else if stateMachine.SubState == SubState_BinanceAntiCreated {
					subProcess_FuturesFilled_Position_BinanceAntiCreatedSubState(tmpFuturesUserData)
				} else if stateMachine.SubState == SubState_FuturesAntiCreated {
					subProcess_FuturesFilled_Position_FuturesAntiCreatedSubState(tmpFuturesUserData)
				} else {
					Error.Printf("Unknown SubState %v\n", stateMachine.SubState)
				}
			default:
				if bCanCreateChanged {
					Info.Println(canCreateSymbolBookTicker)
				}
			}
		} else {
			Error.Printf("Unknow state %v\n", stateMachine.State)
		}
	}
}

func createArbitrageOrder_v2(quoteQty float64, binancePrice, futuresPrice, symbol string) {
	Info.Println(symbol, quoteQty, binancePrice, futuresPrice)
	var bCreateOK, bFuturesCreateOK bool
	var cummulativeQuoteQty, executedQty, executedPrice float64        // 实际交易金额（USDT)，实际交易数量，实际交易均价
	var futuresCummuQuoteQty, futuresExecQty, futuresExecPrice float64 //同上，合约
	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		var err error
		cummulativeQuoteQty, executedQty, executedPrice, err = createBinanceBuyOrder_v2(symbol, binancePrice, quoteQty)
		if err != nil {
			bCreateOK = false
		} else {
			bCreateOK = true
		}
	}()
	wg.Add(1)
	go func() {
		defer wg.Done()
		var err error
		futuresCummuQuoteQty, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder_v2(symbol, futuresPrice, quoteQty)
		if err != nil {
			bFuturesCreateOK = false
		} else {
			bFuturesCreateOK = true
		}
	}()
	wg.Wait()
	Debug.Println(cummulativeQuoteQty, futuresCummuQuoteQty)
	// 如果一个成功另一个失败，成功的也要平掉
	if !bCreateOK && bFuturesCreateOK {
		err := createFuturesBuyOrder(symbol, futuresExecQty)
		if err != nil {
			panic(err)
		}
	} else if !bFuturesCreateOK && bCreateOK {
		err := createBinanceSellOrder(symbol, executedQty)
		if err != nil {
			panic(err)
		}
	} else if bFuturesCreateOK && bCreateOK {
		ppersistence.InsertArbitragePosition(symbol, executedQty, futuresExecQty, executedPrice, futuresExecPrice)
	}
}

func createArbitrageLimitOrder(quoteQty float64, binancePrice, futuresPrice, symbol string) (binanceOrderId, futuresOrderId int64, binanceErr, futuresErr error) {
	binanceOrderId, binanceErr = createBinanceBuyLimitOrder(symbol, binancePrice, quoteQty)
	futuresOrderId, futuresErr = createFuturesSellLimitOrder(symbol, futuresPrice, quoteQty)
	Info.Printf("CreateArbitrageLimitOrder, symbol=%v, binancePrice=%v, futuresPrice=%v, binanceOrderId=%v, futuresOrderId=%v, binanceErr=%v, futuresErr=%v\n",
		symbol, binancePrice, futuresPrice, binanceOrderId, futuresOrderId, binanceErr, futuresErr)
	// 现货单报错，合约单没报错，取消合约单
	if binanceErr != nil && futuresErr == nil {
		err := cancelFuturesLimitOrder(symbol, futuresOrderId)
		if err != nil {
			Warning.Println(err)
			futuresErr = errors.New("future order is already success")
		}
	} else if binanceErr == nil && futuresErr != nil {
		err := cancelBinanceLimitOrder(symbol, binanceOrderId)
		if err != nil {
			Warning.Println(err)
			binanceErr = errors.New("client order is already success")
		}
	}
	return
}

func closeArbitrageLimitOrder(qty, futuresQty float64, binancePrice, futuresPrice, symbol string) (binanceOrderId, futuresOrderId int64, binanceErr, futuresErr error) {
	binanceOrderId, binanceErr = createBinanceSellLimitOrder(symbol, binancePrice, qty)
	futuresOrderId, futuresErr = createFuturesBuyLimitOrder(symbol, futuresPrice, futuresQty)
	Info.Printf("CloseArbitrageLimitOrder, symbol=%v, binancePrice=%v, binanceQty=%v, futuresPrice=%v, futuresQty=%v, binanceOrderId=%v, futuresOrderId=%v, binanceErr=%v, futuresErr=%v\n",
		symbol, binancePrice, qty, futuresPrice, futuresQty, binanceOrderId, futuresOrderId, binanceErr, futuresErr)
	// 现货单报错，合约单没报错，取消合约单
	if binanceErr != nil && futuresErr == nil {
		err := cancelFuturesLimitOrder(symbol, futuresOrderId)
		if err != nil {
			Warning.Println(err)
			futuresErr = errors.New("future order is already success")
		}
	} else if binanceErr == nil && futuresErr != nil {
		err := cancelBinanceLimitOrder(symbol, binanceOrderId)
		if err != nil {
			Warning.Println(err)
			binanceErr = errors.New("client order is already success")
		}
	}
	return
}

func changeState2Position(symbol string, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice float64) {
	dPremiumStage = 0.0

	ppersistence.InsertArbitragePosition(symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
	//symbolPosition = persistence.ArbitragePosition{Symbol: limitOrderSymbolBookTicker.Symbol, SpotCount: binanceExecQty, FutureCount: futuresExecQty, SpotPrice: binanceExecPrice, FuturePrice: futuresExecPrice}
	sp := persistence.ArbitragePosition{Symbol: symbol, SpotCount: binanceExecQty, FutureCount: futuresExecQty, SpotPrice: binanceExecPrice, FuturePrice: futuresExecPrice}

	err := stateMachine.ChangeState(State_Position, sp)
	if err != nil {
		Error.Println(err)
	}
	panic(err) // 测试
}

// 超时处理
func timeout_NotPosition() {
	if stateMachine.SubState == SubState_Init {
		binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceStatus, _ := getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
		futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresStatus, _ := getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
		// 取消当前订单
		err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		err = cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		if binanceStatus == binance.OrderStatusTypeFilled && futuresStatus == futures.OrderStatusTypeFilled {
			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		} else if binanceStatus == binance.OrderStatusTypeFilled {
			if futuresStatus != futures.OrderStatusTypePartiallyFilled {
				futuresBestBidPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, 64)
				if (futuresBestBidPrice-binanceExecPrice)/binanceExecPrice > conf.CreatePremium {
					var err error
					_, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder(canCreateSymbolBookTicker.Symbol, futuresBestBidPrice, conf.QuoteOrderQty)
					if err != nil {
						err = createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
						if err != nil {
							Error.Println(err)
						}

						err = stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					} else {
						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				} else {
					err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					err = stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				}
			} else {
				futuresBestBidPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, 64)
				if (futuresBestBidPrice-binanceExecPrice)/binanceExecPrice > conf.CreatePremium {
					futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder(canCreateSymbolBookTicker.Symbol, futuresBestBidPrice, conf.QuoteOrderQty-futuresExecQuoteQty)
					if err != nil {
						err = createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty-futuresExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, futuresExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					} else {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				} else {
					err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty-futuresExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, futuresExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				}
			}
		} else if futuresStatus == futures.OrderStatusTypeFilled {
			if binanceStatus != binance.OrderStatusTypePartiallyFilled {
				binanceBestAskPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestAskPrice, 64)
				if (futuresExecPrice-binanceBestAskPrice)/binanceBestAskPrice > conf.CreatePremium {
					var err error
					_, binanceExecQty, binanceExecPrice, err = createBinanceBuyOrder(canCreateSymbolBookTicker.Symbol, conf.QuoteOrderQty)
					if err != nil {
						err = createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
						if err != nil {
							Error.Println(err)
						}

						err = stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					} else {
						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				} else {
					err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
					if err != nil {
						Error.Println(err)
					}

					err = stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				}
			} else {
				binanceBestAskPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestAskPrice, 64)
				if (futuresExecPrice-binanceBestAskPrice)/binanceBestAskPrice > conf.CreatePremium {
					binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(canCreateSymbolBookTicker.Symbol, conf.QuoteOrderQty-binanceExecQuoteQty)
					if err != nil {
						err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty-binanceExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, binanceExecQty, binanceExecPrice, futuresExecPrice)
					} else {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				} else {
					err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty-binanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, binanceExecQty, binanceExecPrice, futuresExecPrice)
				}
			}
		} else if binanceStatus == binance.OrderStatusTypePartiallyFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
			if futuresStatus != futures.OrderStatusTypePartiallyFilled {
				futuresBestBidPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, 64)
				if (futuresBestBidPrice-binanceExecPrice)/binanceExecPrice > conf.CreatePremium {
					var err error
					_, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder(canCreateSymbolBookTicker.Symbol, futuresBestBidPrice, binanceExecQuoteQty)
					if err != nil {
						err = createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
						if err != nil {
							Error.Println(err)
						}

						err = stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					} else {
						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				} else {
					err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					err = stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				}
			} else if binanceStatus != binance.OrderStatusTypePartiallyFilled {
				binanceBestAskPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestAskPrice, 64)
				if (futuresExecPrice-binanceBestAskPrice)/binanceBestAskPrice > conf.CreatePremium {
					var err error
					_, binanceExecQty, binanceExecPrice, err = createBinanceBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQuoteQty)
					if err != nil {
						err = createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
						if err != nil {
							Error.Println(err)
						}

						err = stateMachine.ChangeState(State_NotPosition)
						if err != nil {
							Error.Println(err)
						}
					} else {
						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				} else {
					err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
					if err != nil {
						Error.Println(err)
					}

					err = stateMachine.ChangeState(State_NotPosition)
					if err != nil {
						Error.Println(err)
					}
				}
			} else {
				if binanceExecQuoteQty-futuresExecQuoteQty < 1.0 && binanceExecQuoteQty-futuresExecQuoteQty > -1.0 {
					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
				} else if binanceExecQuoteQty > futuresExecQuoteQty {
					futuresBestBidPrice, _ := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, 64)
					futuresExecQuoteQty2, futuresExecQty2, _, err := createFuturesSellOrder(canCreateSymbolBookTicker.Symbol, futuresBestBidPrice, binanceExecQuoteQty-futuresExecQuoteQty)
					if err != nil {
						Error.Println(err)
						err = createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty-futuresExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, futuresExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					} else {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				} else {
					binanceExecQuoteQty2, binanceExecQty2, _, err := createBinanceBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQuoteQty-binanceExecQuoteQty)
					if err != nil {
						Error.Println(err)
						err = createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty-binanceExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, binanceExecQty, binanceExecPrice, futuresExecPrice)
					} else {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
					}
				}
			}
		} else {
			err := stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		}
	} else if stateMachine.SubState == SubState_BinanceAntiCreated {
		var binanceExecQty, futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2 float64
		var binanceStatus binance.OrderStatusType
		var futuresStatus, futuresStatus2 futures.OrderStatusType
		if binanceAntiLimitOrderId != 0 {
			_, binanceExecQty, _, binanceStatus, _ = getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
			err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if futuresLimitOrderId != 0 {
			futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresStatus, _ = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
			err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if futuresAntiLimitOrderId != 0 {
			futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2, futuresStatus2, _ = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
			err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}

		// 处理其他逻辑
		if binanceStatus == binance.OrderStatusTypeFilled {
			if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
				futuresExecQty += futuresExecQty2
			}

			// 合约有成交，平掉合约成交的部分
			if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
				err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
				if err != nil {
					Error.Println(err)
				}
			}

			// 将状态变为未持仓
			err := stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		} else {
			if binanceStatus == binance.OrderStatusTypePartiallyFilled {
				//subStateBinanceExecQuoteQty := subStateBinanceExecPrice * subStateBinanceExecQty
				//subStateBinanceExecQuoteQty -= binanceExecQuoteQty
				subStateBinanceExecQty -= binanceExecQty
				//subStateBinanceExecPrice = subStateBinanceExecQuoteQty / subStateBinanceExecQty
			}

			// 判断合约单是否有成交的，如果有判断跟当前的现货单关系
			if futuresStatus == futures.OrderStatusTypeFilled {
				if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
					// 如果币安反向单部分成交，则需要计算需要平掉的合约仓位，反之只需简单平掉差值即可
					if binanceStatus == binance.OrderStatusTypePartiallyFilled {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty
						err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty-subStateBinanceExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, subStateBinanceExecQty, subStateBinanceExecPrice, futuresExecPrice)
					} else {
						err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty2)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, futuresExecQty, subStateBinanceExecPrice, futuresExecPrice)
					}
				} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty-subStateBinanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, subStateBinanceExecQty, subStateBinanceExecPrice, futuresExecPrice)
				} else {
					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, futuresExecQty, subStateBinanceExecPrice, futuresExecPrice)
				}
			} else if futuresStatus2 == futures.OrderStatusTypeFilled {
				if futuresStatus == futures.OrderStatusTypePartiallyFilled {
					// 如果币安反向单部分成交，则需要计算需要平掉的合约仓位，反之只需简单平掉差值即可
					if binanceStatus == binance.OrderStatusTypePartiallyFilled {
						futuresExecQuoteQty += futuresExecQuoteQty2
						futuresExecQty += futuresExecQty2
						futuresExecPrice = futuresExecQuoteQty / futuresExecQty
						err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty-subStateBinanceExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, subStateBinanceExecQty, subStateBinanceExecPrice, futuresExecPrice)
					} else {
						err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, futuresExecQty2, subStateBinanceExecPrice, futuresExecPrice2)
					}
				} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty2-subStateBinanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, subStateBinanceExecQty, subStateBinanceExecPrice, futuresExecPrice2)
				} else {
					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, futuresExecQty2, subStateBinanceExecPrice, futuresExecPrice2)
				}
			} else if futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
				futuresExecQuoteQty += futuresExecQuoteQty2
				futuresExecQty += futuresExecQty2
				futuresExecPrice = futuresExecQuoteQty / futuresExecQty
				subStateBinanceExecQuoteQty := subStateBinanceExecQty * subStateBinanceExecPrice
				if subStateBinanceExecQuoteQty-futuresExecQuoteQty < 1.0 && subStateBinanceExecQuoteQty-futuresExecQuoteQty > -1.0 {
					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, futuresExecQty, subStateBinanceExecPrice, futuresExecPrice)
				} else if subStateBinanceExecQuoteQty > futuresExecQuoteQty {
					err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty-futuresExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, futuresExecQty, futuresExecQty, subStateBinanceExecPrice, futuresExecPrice)
				} else {
					err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty-subStateBinanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, subStateBinanceExecQty, subStateBinanceExecPrice, futuresExecPrice)
				}
			} else {
				err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty)
				if err != nil {
					Error.Println(err)
				}
				// 将状态变为未持仓
				err = stateMachine.ChangeState(State_NotPosition)
				if err != nil {
					Error.Println(err)
				}
			}
		}
	} else if stateMachine.SubState == SubState_FuturesAntiCreated {
		var binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceExecQuoteQty2, binanceExecQty2, binanceExecPrice2, futuresExecQty float64
		var binanceStatus, binanceStatus2 binance.OrderStatusType
		var futuresStatus futures.OrderStatusType
		if binanceLimitOrderId != 0 {
			binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceStatus, _ = getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
			err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if binanceAntiLimitOrderId != 0 {
			binanceExecQuoteQty2, binanceExecQty2, binanceExecPrice2, binanceStatus2, _ = getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
			err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		if futuresAntiLimitOrderId != 0 {
			_, futuresExecQty, _, futuresStatus, _ = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
			err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}

		// 处理其他逻辑
		if futuresStatus == futures.OrderStatusTypeFilled {
			if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
				binanceExecQty += binanceExecQty2
			}

			// 现货有成交，平掉现货成交的部分
			if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus == binance.OrderStatusTypePartiallyFilled || binanceStatus2 == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
				err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
				if err != nil {
					Error.Println(err)
				}
			}

			// 将状态变为未持仓
			err := stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
		} else {
			if futuresStatus == futures.OrderStatusTypePartiallyFilled {
				//subStateFuturesExecQuoteQty := subStateFuturesExecPrice * subStateFuturesExecQty
				//subStateFuturesExecQuoteQty -= futuresExecQuoteQty
				subStateFuturesExecQty -= futuresExecQty
				//subStateFuturesExecPrice = subStateFuturesExecQuoteQty / subStateFuturesExecQty
			}

			// 判断现货单是否有成交的，如果有判断跟当前的合约单关系
			if binanceStatus == binance.OrderStatusTypeFilled {
				if binanceStatus2 == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
					// 如果币安反向单部分成交，则需要计算需要平掉的合约仓位，反之只需简单平掉差值即可
					if futuresStatus == futures.OrderStatusTypePartiallyFilled {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty
						err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty-subStateFuturesExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, subStateFuturesExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
					} else {
						err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty2)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
					}
				} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
					err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty-subStateFuturesExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateFuturesExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
				} else {
					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
				}
			} else if binanceStatus2 == binance.OrderStatusTypeFilled {
				if binanceStatus == binance.OrderStatusTypePartiallyFilled {
					// 如果币安反向单部分成交，则需要计算需要平掉的合约仓位，反之只需简单平掉差值即可
					if futuresStatus == futures.OrderStatusTypePartiallyFilled {
						binanceExecQuoteQty += binanceExecQuoteQty2
						binanceExecQty += binanceExecQty2
						binanceExecPrice = binanceExecQuoteQty / binanceExecQty
						err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty-subStateFuturesExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, subStateFuturesExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
					} else {
						err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
						if err != nil {
							Error.Println(err)
						}

						// 状态改为持仓
						changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty2, subStateFuturesExecQty, binanceExecPrice2, subStateFuturesExecPrice)
					}
				} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
					err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty2-subStateFuturesExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateFuturesExecQty, subStateFuturesExecQty, binanceExecPrice2, subStateFuturesExecPrice)
				} else {
					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty2, subStateFuturesExecQty, binanceExecPrice2, subStateFuturesExecPrice)
				}
			} else if binanceStatus == binance.OrderStatusTypePartiallyFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
				binanceExecQuoteQty += binanceExecQuoteQty2
				binanceExecQty += binanceExecQty2
				binanceExecPrice = binanceExecQuoteQty / binanceExecQty
				subStateFuturesExecQuoteQty := subStateFuturesExecQty * subStateFuturesExecPrice
				if subStateFuturesExecQuoteQty-binanceExecQuoteQty < 1.0 && subStateFuturesExecQuoteQty-binanceExecQuoteQty > -1.0 {
					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
				} else if subStateFuturesExecQuoteQty > binanceExecQuoteQty {
					err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, subStateFuturesExecQty-binanceExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, binanceExecQty, binanceExecPrice, subStateFuturesExecPrice)
				} else {
					err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty-subStateFuturesExecQty)
					if err != nil {
						Error.Println(err)
					}

					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateFuturesExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
				}
			} else {
				err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, subStateFuturesExecQty)
				if err != nil {
					Error.Println(err)
				}
				// 将状态变为未持仓
				err = stateMachine.ChangeState(State_NotPosition)
				if err != nil {
					Error.Println(err)
				}
			}
		}
	} else {
		Error.Printf("Unknow SubState %v\n", stateMachine.SubState)
	}
}

// 子状态变化处理
func subProcess_BinanceFilled_NotPosition_InitSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	_, binanceExecQty, binanceExecPrice, binanceStatus, binanceErr := getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance Order Status is %v, err is %v\n", binanceStatus, binanceErr)
		return
	}

	// 判断当前合约单状态，如果此时已经成交，则可以直接转为持仓，如果此时部分成交，则等待全部成交即可
	_, futuresExecQty, futuresExecPrice, futuresStatus, _ := getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
	if futuresStatus == futures.OrderStatusTypeFilled {
		changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		return
	} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
		Info.Printf("FuturesOrder %v is Partially Filled. Please wait\n", futuresLimitOrderId)
		return
	}

	bFuturesMarket := true
	// 判断当前系统中合约买单的最优挂单价是否和当前成交的现货价格达到配置的溢价差，如果达到，判断当前挂单总价是否是成交额的配置的倍数，如果都符合，挂市价卖单直接吃单
	futuresBestBidPrice, err := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestBidPrice, 64)
	if err != nil {
		Error.Printf("FuturesBookTicker.BestBidPrice is not Float64, err = %v\n", err)
		bFuturesMarket = false
	}
	futuresBestBidQty, err := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestBidQty, 64)
	if err != nil {
		Error.Printf("FuturesBookTicker.BestBidQty is not Float64, err = %v\n", err)
		bFuturesMarket = false
	}

	if (futuresBestBidPrice-binanceExecPrice)/binanceExecPrice > conf.GreatCreatePremium &&
		futuresBestBidPrice*futuresBestBidQty > conf.QuoteMultiple*conf.QuoteOrderQty {
		bFuturesMarket = true
	} else {
		bFuturesMarket = false
	}

	if bFuturesMarket {
		// 创建合约市价单，并取消合约挂单
		// 取消当前合约限价单
		err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		_, futuresExecQty, futuresExecPrice, err = createFuturesSellOrder(canCreateSymbolBookTicker.Symbol, futuresBestBidPrice, conf.QuoteOrderQty)
		if err != nil {
			Error.Println(err)
			bFuturesMarket = false
		} else {
			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		}
	}
	if !bFuturesMarket {
		var priceBinancePrecision, priceFuturesPrecision int
		exchangeInfo, bOK := symbolExchangeInfos[canCreateSymbolBookTicker.Symbol]
		if !bOK {
			err := errors.New("symbol precision unknown")
			Warning.Println(err)
			panic(err)
		}
		priceBinancePrecision = exchangeInfo.SpotPricePrecision
		priceFuturesPrecision = exchangeInfo.FuturesPricePrecision
		sBinanceAntiPrice := strconv.FormatFloat(binanceExecPrice*(1+conf.CreatePremium), 'f', priceBinancePrecision, 64)
		sFuturesAntiPrice := strconv.FormatFloat(binanceExecPrice*(1+conf.CreatePremium), 'f', priceFuturesPrecision, 64)
		Info.Println(sBinanceAntiPrice, sFuturesAntiPrice)
		antiOrderId, err := createBinanceSellLimitOrder(canCreateSymbolBookTicker.Symbol, sBinanceAntiPrice, binanceExecQty)
		if err != nil {
			Error.Println(err)
			antiOrderId = 0
		}
		var antiFuturesOrderId int64
		antiFuturesOrderId = 0
		if dPremiumStage-conf.CreatePremium > 0.002 {
			antiFuturesOrderId, err = createFuturesSellLimitOrder(canCreateSymbolBookTicker.Symbol, sFuturesAntiPrice, conf.QuoteOrderQty)
			if err != nil {
				Error.Println(err)
				antiFuturesOrderId = 0
			}
		}
		stateMachine.ChangeSubState(SubState_BinanceAntiCreated, antiOrderId, antiFuturesOrderId, binanceExecQty, binanceExecPrice)
	}
}

func subProcess_BinanceFilled_NotPosition_BinanceAntiCreatedSubState() {
	if binanceAntiLimitOrderId == 0 {
		Warning.Println("binanceAntiLimitOrderId == 0")
		return
	}
	_, _, _, binanceStatus, binanceErr := getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance AntiOrder Status is %v, err is %v\n", binanceStatus, binanceErr)
		return
	}

	var futuresExecQty, futuresExecQty2 float64
	var futuresStatus, futuresStatus2 futures.OrderStatusType
	// 将合约单取消
	if futuresLimitOrderId != 0 {
		_, futuresExecQty, _, futuresStatus, _ = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
		err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	// 将创建的合约适配单取消
	if futuresAntiLimitOrderId != 0 {
		_, futuresExecQty2, _, futuresStatus2, _ = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
		err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}

	// 如果合约单有成交，平掉
	if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
		if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
			futuresExecQty += futuresExecQty2
		}
		err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
		if err != nil {
			Error.Println(err)
		}
	}
	// 将状态转为非持仓状态
	err := stateMachine.ChangeState(State_NotPosition)
	if err != nil {
		Error.Println(err)
	}
}

func subProcess_BinanceFilled_NotPosition_FuturesAntiCreatedSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	var binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceExecQuoteQty2, binanceExecQty2, binanceExecPrice2 float64
	var binanceStatus, binanceStatus2 binance.OrderStatusType
	var binanceErr, binanceErr2 error
	var bBinanceFilled = false
	if binanceLimitOrderId != 0 {
		binanceExecQuoteQty, binanceExecQty, binanceExecPrice, binanceStatus, binanceErr = getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
		if binanceStatus == binance.OrderStatusTypeFilled {
			bBinanceFilled = true
		} else {
			Warning.Printf("Binance Order %v status is %v, err is %v\n", binanceLimitOrderId, binanceStatus, binanceErr)
		}
	}
	if binanceAntiLimitOrderId != 0 {
		binanceExecQuoteQty2, binanceExecQty2, binanceExecPrice2, binanceStatus2, binanceErr2 = getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
		if binanceStatus2 == binance.OrderStatusTypeFilled {
			bBinanceFilled = true
		} else {
			Warning.Printf("Binance Order %v status is %v, err is %v\n", binanceAntiLimitOrderId, binanceStatus2, binanceErr2)
		}
	}
	if bBinanceFilled == false {
		return
	}

	// 关闭当前的现货单
	if binanceLimitOrderId != 0 {
		err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if binanceAntiLimitOrderId != 0 {
		err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}

	if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus == binance.OrderStatusTypePartiallyFilled {
		if binanceStatus2 == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
			binanceExecQuoteQty += binanceExecQuoteQty2
			binanceExecQty += binanceExecQty2
			binanceExecPrice = binanceExecQuoteQty / binanceExecQty
		}
	} else {
		if binanceStatus2 == binance.OrderStatusTypeFilled || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
			binanceExecQuoteQty = binanceExecQuoteQty2
			binanceExecQty = binanceExecQty2
			binanceExecPrice = binanceExecPrice2
		}
	}

	bFuturesNotPosition := false
	if futuresAntiLimitOrderId != 0 {
		_, futuresExecQty, _, futuresStatus, _ := getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
		err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		// 如果合约反向单完全成交，则应将状态转为未持仓
		if futuresStatus == futures.OrderStatusTypeFilled {
			bFuturesNotPosition = true
		} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
			subStateFuturesExecQty -= futuresExecQty
		}
	}

	if bFuturesNotPosition {
		err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
		if err != nil {
			Error.Println(err)
		}
		// 将状态转为非持仓状态
		err = stateMachine.ChangeState(State_NotPosition)
		if err != nil {
			Error.Println(err)
		}
	} else {
		subStateFuturesExecQuoteQty := subStateFuturesExecQty * subStateFuturesExecPrice
		if subStateFuturesExecQuoteQty-binanceExecQuoteQty < 1.0 && subStateFuturesExecQuoteQty-binanceExecQuoteQty > -1.0 {
			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
		} else if subStateFuturesExecQuoteQty > binanceExecQuoteQty {
			err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, subStateFuturesExecQty-binanceExecQty)
			if err != nil {
				Error.Println(err)
			}

			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, binanceExecQty, binanceExecPrice, subStateFuturesExecPrice)
		} else {
			err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty-subStateFuturesExecQty)
			if err != nil {
				Error.Println(err)
			}

			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, subStateFuturesExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
		}
	}

	/*
		if binanceErr != nil || binanceStatus != binance.OrderStatusTypeFilled {
			Warning.Printf("Binance Order Status is %v, err is %v\n", binanceStatus, binanceErr)
			if binanceAntiLimitOrderId != 0 {
				_, binanceExecQty, binanceExecPrice, binanceStatus, binanceErr := getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
				if binanceErr != nil || binanceStatus != binance.OrderStatusTypeFilled {
					Warning.Printf("Binance Order Status is %v, err is %v\n", binanceStatus, binanceErr)
				} else {
					if futuresAntiLimitOrderId != 0 {
						err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
						if err != nil {
							Error.Println(err)
						}
					}
					if binanceLimitOrderId != 0 {
						err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
						if err != nil {
							Error.Println(err)
						}
					}
					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
				}
			}
		} else {
			if futuresAntiLimitOrderId != 0 {
				err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
				if err != nil {
					Error.Println(err)
				}
			}
			if binanceAntiLimitOrderId != 0 {
				err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
				if err != nil {
					Error.Println(err)
				}
			}
			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, subStateFuturesExecQty, binanceExecPrice, subStateFuturesExecPrice)
		}
	*/
}

func subProcess_FuturesFilled_NotPosition_InitSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	if futuresLimitOrderId == 0 {
		Warning.Println("futuresLimitOrderId == 0")
		return
	}
	_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr := getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
	if futuresStatus != futures.OrderStatusTypeFilled {
		Warning.Printf("Futures Order Status is %v, err is %v\n", futuresStatus, futuresErr)
		return
	}

	// 判断当前合约单状态，如果此时已经成交，则可以直接转为持仓，如果此时部分成交，则等待全部成交即可
	_, binanceExecQty, binanceExecPrice, binanceStatus, _ := getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
	if binanceStatus == binance.OrderStatusTypeFilled {
		changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		return
	} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
		Info.Printf("BinanceOrder %v is Partially Filled. Please wait\n", binanceLimitOrderId)
		return
	}

	bBinanceMarket := true
	// 判断当前系统中合约买单的最优挂单价是否和当前成交的现货价格达到配置的溢价差，如果达到，判断当前挂单总价是否是成交额的配置的倍数，如果都符合，挂市价卖单直接吃单
	binanceBestAskPrice, err := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestAskPrice, 64)
	if err != nil {
		Error.Printf("BinanceBookTicker.BestAskPrice is not Float64, err = %v\n", err)
		bBinanceMarket = false
	}
	binanceBestAskQty, err := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestAskQty, 64)
	if err != nil {
		Error.Printf("BinanceBookTicker.BestAskQty is not Float64, err = %v\n", err)
		bBinanceMarket = false
	}

	if (futuresExecQty-binanceBestAskPrice)/binanceBestAskPrice > conf.GreatCreatePremium &&
		binanceBestAskPrice*binanceBestAskQty > conf.QuoteMultiple*conf.QuoteOrderQty {
		bBinanceMarket = true
	} else {
		bBinanceMarket = false
	}

	if bBinanceMarket {
		// 取消当前现货限价单
		err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		_, binanceExecQty, binanceExecPrice, err = createBinanceBuyOrder(canCreateSymbolBookTicker.Symbol, conf.QuoteOrderQty)
		if err != nil {
			Error.Println(err)
			bBinanceMarket = false
		} else {
			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, binanceExecQty, futuresExecQty, binanceExecPrice, futuresExecPrice)
		}
	}
	if !bBinanceMarket {
		var priceFuturesPrecision, priceBinancePrecision int
		exchangeInfo, bOK := symbolExchangeInfos[canCreateSymbolBookTicker.Symbol]
		if !bOK {
			err := errors.New("symbol precision unknown")
			Warning.Println(err)
			panic(err)
		}
		priceFuturesPrecision = exchangeInfo.FuturesPricePrecision
		priceBinancePrecision = exchangeInfo.SpotPricePrecision
		sFuturesAntiPrice := strconv.FormatFloat(futuresExecPrice*(1-conf.CreatePremium), 'f', priceFuturesPrecision, 64)
		sBinanceAntiPrice := strconv.FormatFloat(futuresExecPrice*(1-conf.CreatePremium), 'f', priceBinancePrecision, 64)
		Info.Println(sFuturesAntiPrice, sBinanceAntiPrice)
		antiFuturesOrderId, err := createFuturesBuyLimitOrder(canCreateSymbolBookTicker.Symbol, sFuturesAntiPrice, futuresExecQty)
		if err != nil {
			Error.Println(err)
			antiFuturesOrderId = 0
		}
		var antiBinanceOrderId int64
		antiBinanceOrderId = 0
		if dPremiumStage-conf.CreatePremium > 0.002 {
			antiBinanceOrderId, err = createBinanceBuyLimitOrder(canCreateSymbolBookTicker.Symbol, sBinanceAntiPrice, conf.QuoteOrderQty)
			if err != nil {
				Error.Println(err)
			}
		}
		stateMachine.ChangeSubState(SubState_FuturesAntiCreated, antiFuturesOrderId, antiBinanceOrderId, futuresExecQty, futuresExecPrice)
	}
}

func subProcess_FuturesFilled_NotPosition_FuturesAntiCreatedSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	if futuresAntiLimitOrderId == 0 {
		Warning.Println("futuresAntiLimitOrderId == 0")
		return
	}
	_, _, _, futuresStatus, futuresErr := getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
	if futuresStatus != futures.OrderStatusTypeFilled {
		Warning.Printf("Futures AntiOrder Status is %v, err is %v\n", futuresStatus, futuresErr)
		return
	}
	/*
		var futuresExecQty, futuresExecQty2 float64
		var futuresStatus, futuresStatus2 futures.OrderStatusType
		var futuresErr, futuresErr2 error
		// 将合约单取消
		if futuresLimitOrderId != 0 {
			_, futuresExecQty, _, futuresStatus, futuresErr = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
			err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
		// 将创建的合约适配单取消
		if futuresAntiLimitOrderId != 0 {
			_, futuresExecQty2, _, futuresStatus2, futuresErr2 = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
			err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
			if err != nil {
				Error.Println(err)
			}
		}
	*/

	var binanceExecQty, binanceExecQty2 float64
	var binanceStatus, binanceStatus2 binance.OrderStatusType
	var binanceErr, binanceErr2 error
	if binanceLimitOrderId != 0 {
		_, binanceExecQty, _, binanceStatus, binanceErr = getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
		err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if binanceAntiLimitOrderId != 0 {
		_, binanceExecQty2, _, binanceStatus2, binanceErr2 = getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
		err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if binanceErr == nil || binanceStatus == binance.OrderStatusTypePartiallyFilled || binanceErr2 == nil || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
		if binanceErr == nil || binanceStatus == binance.OrderStatusTypePartiallyFilled {
			if binanceErr2 == nil || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
				binanceExecQty += binanceExecQty2
			}
		} else if binanceErr2 == nil || binanceStatus2 == binance.OrderStatusTypePartiallyFilled {
			binanceExecQty = binanceExecQty2
		}
		err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, binanceExecQty)
		if err != nil {
			Error.Println(err)
		}
	}
	// 将状态转为非持仓状态
	err := stateMachine.ChangeState(State_NotPosition)
	if err != nil {
		Error.Println(err)
	}
}

func subProcess_FuturesFilled_NotPosition_BinanceAntiCreatedSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	var futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2 float64
	var futuresStatus, futuresStatus2 futures.OrderStatusType
	var futuresErr, futuresErr2 error
	var bFuturesFilled = false
	if futuresLimitOrderId != 0 {
		futuresExecQuoteQty, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
		if futuresStatus == futures.OrderStatusTypeFilled {
			bFuturesFilled = true
		} else {
			Warning.Printf("Futures Order %v status is %v, err is %v\n", futuresLimitOrderId, futuresStatus, futuresErr)
		}
	}
	if futuresAntiLimitOrderId != 0 {
		futuresExecQuoteQty2, futuresExecQty2, futuresExecPrice2, futuresStatus2, futuresErr2 = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
		if futuresStatus2 == futures.OrderStatusTypeFilled {
			bFuturesFilled = true
		} else {
			Warning.Printf("Futures Order %v status is %v, err is %v\n", futuresAntiLimitOrderId, futuresStatus2, futuresErr2)
		}
	}
	if bFuturesFilled == false {
		return
	}

	if futuresLimitOrderId != 0 {
		err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if futuresAntiLimitOrderId != 0 {
		err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
		if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
			futuresExecQuoteQty += futuresExecQuoteQty2
			futuresExecQty += futuresExecQty2
			futuresExecPrice = futuresExecQuoteQty / futuresExecQty
		}
	} else {
		if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
			futuresExecQuoteQty = futuresExecQuoteQty2
			futuresExecQty = futuresExecQty2
			futuresExecPrice = futuresExecPrice2
		}
	}

	bBinanceNotPosition := false
	if binanceAntiLimitOrderId != 0 {
		_, binanceExecQty, _, binanceStatus, _ := getBinanceOrderInf(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
		err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		// 如果合约反向单完全成交，则应将状态转为未持仓
		if binanceStatus == binance.OrderStatusTypeFilled {
			bBinanceNotPosition = true
		} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
			subStateBinanceExecQty -= binanceExecQty
		}
	}

	if bBinanceNotPosition {
		err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty)
		if err != nil {
			Error.Println(err)
		}
		// 将状态转为非持仓状态
		err = stateMachine.ChangeState(State_NotPosition)
		if err != nil {
			Error.Println(err)
		}
	} else {
		subStateBinanceExecQuoteQty := subStateBinanceExecQty * subStateBinanceExecPrice
		if subStateBinanceExecQuoteQty-futuresExecQuoteQty < 1.0 && subStateBinanceExecQuoteQty-futuresExecQuoteQty > -1.0 {
			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, futuresExecQty, subStateBinanceExecPrice, futuresExecPrice)
		} else if subStateBinanceExecQuoteQty > futuresExecQuoteQty {
			err := createBinanceSellOrder(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty-futuresExecQty)
			if err != nil {
				Error.Println(err)
			}

			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, futuresExecQty, futuresExecQty, subStateBinanceExecPrice, futuresExecPrice)
		} else {
			err := createFuturesBuyOrder(canCreateSymbolBookTicker.Symbol, futuresExecQty-subStateBinanceExecQty)
			if err != nil {
				Error.Println(err)
			}

			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, subStateBinanceExecQty, subStateBinanceExecPrice, futuresExecPrice)
		}
	}

	// 老版处理逻辑
	/*
		_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr := getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
		if futuresErr != nil || futuresStatus != futures.OrderStatusTypeFilled {
			Warning.Printf("Futures Order Status is %v, err is %v\n", futuresStatus, futuresErr)
			if futuresAntiLimitOrderId != 0 {
				_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr = getFuturesOrderInf(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
				if futuresErr != nil || futuresStatus != futures.OrderStatusTypeFilled {
					Warning.Printf("Futures Order Status is %v, err is %v\n", futuresStatus, futuresErr)
				} else {
					if binanceAntiLimitOrderId != 0 {
						err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
						if err != nil {
							Error.Println(err)
						}
					}
					if futuresLimitOrderId != 0 {
						err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
						if err != nil {
							Error.Println(err)
						}
					}
					// 状态改为持仓
					changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, futuresExecQty, subStateBinanceExecPrice, futuresExecPrice)
				}
			}
		} else {
			if binanceAntiLimitOrderId != 0 {
				err := cancelBinanceLimitOrder(canCreateSymbolBookTicker.Symbol, binanceAntiLimitOrderId)
				if err != nil {
					Error.Println(err)
				}
			}
			if futuresAntiLimitOrderId != 0 {
				err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
				if err != nil {
					Error.Println(err)
				}
			}
			// 状态改为持仓
			changeState2Position(canCreateSymbolBookTicker.Symbol, subStateBinanceExecQty, futuresExecQty, subStateBinanceExecPrice, futuresExecPrice)
		}
	*/
}

func subProcess_BinanceFilled_Position_InitSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	_, binanceExecQty, binanceExecPrice, binanceStatus, binanceErr := getBinanceOrderInf(symbolPosition.Symbol, binanceLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance Order Status is %v, err is %v\n", binanceStatus, binanceErr)
		return
	}

	// 判断当前合约单状态，如果此时已经成交，则可以直接转为持仓，如果此时部分成交，则等待全部成交即可
	_, _, _, futuresStatus, _ := getFuturesOrderInf(symbolPosition.Symbol, futuresLimitOrderId)
	if futuresStatus == futures.OrderStatusTypeFilled {
		// 将状态转为非持仓状态
		err := ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
		if err != nil {
			Error.Println(err)
		}
		err = stateMachine.ChangeState(State_NotPosition)
		if err != nil {
			Error.Println(err)
		}
		panic(err)
		return
	} else if futuresStatus == futures.OrderStatusTypePartiallyFilled {
		Info.Printf("FuturesOrder %v is Partially Filled. Please wait\n", futuresLimitOrderId)
		return
	}

	bFuturesMarket := true
	// 判断当前系统中合约买单的最优挂单价是否和当前成交的现货价格达到配置的溢价差，如果达到，判断当前挂单总价是否是成交额的配置的倍数，如果都符合，挂市价卖单直接吃单
	futuresBestAskPrice, err := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestAskPrice, 64)
	if err != nil {
		Error.Printf("FuturesBookTicker.BestAskPrice is not Float64, err = %v\n", err)
		bFuturesMarket = false
	}
	futuresBestAskQty, err := strconv.ParseFloat(canCreateSymbolBookTicker.FuturesBookTicker.BestAskQty, 64)
	if err != nil {
		Error.Printf("FuturesBookTicker.BestAskQty is not Float64, err = %v\n", err)
		bFuturesMarket = false
	}

	if (futuresBestAskPrice-binanceExecPrice)/binanceExecPrice < conf.GreatClosePremium &&
		futuresBestAskPrice*futuresBestAskQty > conf.QuoteMultiple*conf.QuoteOrderQty {
		bFuturesMarket = true
	} else {
		bFuturesMarket = false
	}

	if bFuturesMarket {
		// 创建合约市价单，并取消合约挂单
		// 取消当前合约限价单
		err := cancelFuturesLimitOrder(symbolPosition.Symbol, futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		err = createFuturesBuyOrder(symbolPosition.Symbol, symbolPosition.FutureCount)
		if err != nil {
			Error.Println(err)
			bFuturesMarket = false
		} else {
			// 将状态转为非持仓状态
			err := ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
			if err != nil {
				Error.Println(err)
			}
			// 将状态转为非持仓状态
			err = stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
			panic(err)
		}
	}
	if !bFuturesMarket {
		cummuQuoteQty, _ := strconv.ParseFloat(tmpBinanceFilledOrder.CummuQuoteQty, 64)
		executedQty, _ := strconv.ParseFloat(tmpBinanceFilledOrder.ExecutedQty, 64)
		avgPrice := cummuQuoteQty / executedQty
		var spotPricePrecision, futuresPricePrecision int
		exchangeInfo, bOK := symbolExchangeInfos[symbolPosition.Symbol]
		if !bOK {
			err := errors.New("symbol precision unknown")
			Warning.Println(err)
			panic(err)
		}
		spotPricePrecision = exchangeInfo.SpotPricePrecision
		futuresPricePrecision = exchangeInfo.FuturesPricePrecision
		sBinanceAntiPrice := strconv.FormatFloat(avgPrice/(1+conf.CreatePremium), 'f', spotPricePrecision, 64)
		sFuturesAntiPrice := strconv.FormatFloat(avgPrice*(1+conf.ClosePremium), 'f', futuresPricePrecision, 64)
		Info.Println(sBinanceAntiPrice, sFuturesAntiPrice)
		antiBinanceOrderId, err := createBinanceBuyLimitOrder(symbolPosition.Symbol, sBinanceAntiPrice, executedQty)
		if err != nil {
			Error.Println(err)
		}
		antiFuturesOrderId, err := createFuturesBuyLimitOrder(symbolPosition.Symbol, sFuturesAntiPrice, symbolPosition.FutureCount)
		if err != nil {
			Error.Println(err)
		}
		stateMachine.ChangeSubState(SubState_BinanceAntiCreated, antiBinanceOrderId, antiFuturesOrderId, binanceExecQty, binanceExecPrice)
	}
}

func subProcess_BinanceFilled_Position_BinanceAntiCreatedSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	if binanceAntiLimitOrderId == 0 {
		Warning.Println("binanceAntiLimitOrderId == 0")
		return
	}
	_, _, _, binanceStatus, binanceErr := getBinanceOrderInf(symbolPosition.Symbol, binanceAntiLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance AntiOrder Status is %v, err is %v\n", binanceStatus, binanceErr)
		return
	}

	var futuresExecQuoteQty, futuresExecQuoteQty2, futuresExecQty, futuresExecQty2, futuresExecPrice float64
	var futuresStatus, futuresStatus2 futures.OrderStatusType
	// 将合约单取消
	if futuresLimitOrderId != 0 {
		futuresExecQuoteQty, futuresExecQty, _, futuresStatus, _ = getFuturesOrderInf(symbolPosition.Symbol, futuresLimitOrderId)
		err := cancelFuturesLimitOrder(symbolPosition.Symbol, futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	// 将创建的合约适配单取消
	if futuresAntiLimitOrderId != 0 {
		futuresExecQuoteQty2, futuresExecQty2, _, futuresStatus2, _ = getFuturesOrderInf(symbolPosition.Symbol, futuresAntiLimitOrderId)
		err := cancelFuturesLimitOrder(symbolPosition.Symbol, futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}

	// 如果合约单有成交，平掉
	if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled || futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
		if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
			futuresExecQty += futuresExecQty2
			futuresExecQuoteQty += futuresExecQuoteQty2
			futuresExecPrice = futuresExecQuoteQty / futuresExecQty
		}
		_, _, _, err := createFuturesSellOrder(symbolPosition.Symbol, futuresExecPrice, futuresExecQuoteQty)
		if err != nil {
			Error.Println(err)
		}
	}
	// 将状态转为持仓状态
	err := stateMachine.ChangeState(State_Position, symbolPosition)
	if err != nil {
		Error.Println(err)
	}
}

func subProcess_BinanceFilled_Position_FuturesAntiCreatedSubState(tmpBinanceFilledOrder binance.WsExecutionReportEvent) {
	if binanceLimitOrderId == 0 {
		Error.Println("binanceLimitOrderId == 0")
		return
	}

	_, _, _, binanceStatus, binanceErr := getBinanceOrderInf(symbolPosition.Symbol, binanceLimitOrderId)
	if binanceStatus != binance.OrderStatusTypeFilled {
		Warning.Printf("Binance Order %v status is %v, err is %v\n", binanceLimitOrderId, binanceStatus, binanceErr)
		return
	}

	// 关闭当前的现货单
	err := cancelBinanceLimitOrder(symbolPosition.Symbol, binanceLimitOrderId)
	if err != nil {
		Error.Println(err)
	}

	if futuresAntiLimitOrderId != 0 {
		_, futuresExecQty, _, futuresStatus, _ := getFuturesOrderInf(symbolPosition.Symbol, futuresAntiLimitOrderId)
		err := cancelFuturesLimitOrder(symbolPosition.Symbol, futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
		// 如果合约反向单完全成交，则应将状态转为未持仓
		if futuresStatus == futures.OrderStatusTypeFilled || futuresStatus == futures.OrderStatusTypePartiallyFilled {
			err = createFuturesBuyOrder(symbolPosition.Symbol, futuresExecQty)
			if err != nil {
				Error.Println(err)
			}
		}
	}

	// 将状态转为非持仓状态
	err = ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
	if err != nil {
		Error.Println(err)
	}

	err = stateMachine.ChangeState(State_NotPosition)
	if err != nil {
		Error.Println(err)
	}
	panic(err) // 测试
}

func subProcess_FuturesFilled_Position_InitSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	if futuresLimitOrderId == 0 {
		Error.Println("futuresLimitOrderId == 0")
		return
	}
	_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr := getFuturesOrderInf(symbolPosition.Symbol, futuresLimitOrderId)
	if futuresStatus != futures.OrderStatusTypeFilled {
		Warning.Printf("Futures Order Status is %v, err is %v\n", futuresStatus, futuresErr)
		return
	}
	if binanceLimitOrderId != 0 {
		_, _, _, binanceStatus, _ := getBinanceOrderInf(symbolPosition.Symbol, binanceLimitOrderId)
		if binanceStatus == binance.OrderStatusTypeFilled {
			// 将状态转为非持仓状态
			err := ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
			if err != nil {
				Error.Println(err)
				panic(err)
			}

			err = stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
			panic(err) // 测试
			return
		} else if binanceStatus == binance.OrderStatusTypePartiallyFilled {
			Info.Printf("BinanceOrder %v is Partially Filled. Please wait\n", binanceLimitOrderId)
			return
		}
	}

	bBinanceMarket := true
	// 判断当前系统中合约买单的最优挂单价是否和当前成交的现货价格达到配置的溢价差，如果达到，判断当前挂单总价是否是成交额的配置的倍数，如果都符合，挂市价卖单直接吃单
	binanceBestBidPrice, err := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestBidPrice, 64)
	if err != nil {
		Error.Printf("BinanceBookTicker.BestBidPrice is not Float64, err = %v\n", err)
		bBinanceMarket = false
	}
	binanceBestBidQty, err := strconv.ParseFloat(canCreateSymbolBookTicker.BinanceBookTicker.BestBidQty, 64)
	if err != nil {
		Error.Printf("BinanceBookTicker.BestBidQty is not Float64, err = %v\n", err)
		bBinanceMarket = false
	}

	if (futuresExecPrice-binanceBestBidPrice)/binanceBestBidPrice < conf.GreatClosePremium &&
		binanceBestBidPrice*binanceBestBidQty > conf.QuoteMultiple*conf.QuoteOrderQty {
		bBinanceMarket = true
	} else {
		bBinanceMarket = false
	}

	if bBinanceMarket {
		err := cancelBinanceLimitOrder(symbolPosition.Symbol, binanceLimitOrderId)
		if err != nil {
			Error.Println(err)
		}

		err = createBinanceSellOrder(symbolPosition.Symbol, symbolPosition.SpotCount)
		if err != nil {
			Error.Println(err)
			bBinanceMarket = false
		} else {
			// 将状态转为持仓状态
			err := ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
			if err != nil {
				Error.Println(err)
				panic(err)
			}

			err = stateMachine.ChangeState(State_NotPosition)
			if err != nil {
				Error.Println(err)
			}
			panic(err) // 测试
		}
	}
	if !bBinanceMarket {
		var pricePrecision int
		exchangeInfo, bOK := symbolExchangeInfos[symbolPosition.Symbol]
		if !bOK {
			err := errors.New("symbol precision unknown")
			Warning.Println(err)
			panic(err)
		}
		pricePrecision = exchangeInfo.FuturesPricePrecision
		sAntiPrice := strconv.FormatFloat(futuresExecPrice*(1+conf.CreatePremium), 'f', pricePrecision, 64)
		antiOrderId, err := createFuturesSellLimitOrder(symbolPosition.Symbol, sAntiPrice, futuresExecQty)
		if err != nil {
			Error.Println(err)
		}
		stateMachine.ChangeSubState(SubState_FuturesAntiCreated, antiOrderId, 0, futuresExecQty, futuresExecPrice)
	}
}

func subProcess_FuturesFilled_Position_FuturesAntiCreatedSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	if futuresAntiLimitOrderId == 0 {
		Error.Println("futuresAntiLimitOrderId == 0")
		return
	}
	_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr := getFuturesOrderInf(symbolPosition.Symbol, futuresAntiLimitOrderId)
	if futuresStatus != futures.OrderStatusTypeFilled {
		Warning.Printf("Futures AntiOrder Status is %v, err is %v\n", futuresStatus, futuresErr)
		return
	}

	binanceExecQuoteQty, _, _, binanceStatus, _ := getBinanceOrderInf(symbolPosition.Symbol, binanceLimitOrderId)
	err := cancelBinanceLimitOrder(symbolPosition.Symbol, binanceLimitOrderId)
	if err != nil {
		Error.Println(err)
	}
	if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus == binance.OrderStatusTypePartiallyFilled {
		_, _, _, err := createBinanceBuyOrder(symbolPosition.Symbol, binanceExecQuoteQty)
		if err != nil {
			Error.Println(err)
		}
	}
	// 更新数据库
	// Todo
	// 将状态转为非持仓状态
	symbolPosition.FuturePrice = futuresExecPrice
	symbolPosition.FutureCount = futuresExecQty
	err = stateMachine.ChangeState(State_Position, symbolPosition)
	if err != nil {
		Error.Println(err)
	}
}

func subProcess_FuturesFilled_Position_BinanceAntiCreatedSubState(tmpFuturesUserData futures.WsOrderTradeUpdate) {
	var futuresExecQty, futuresExecPrice, futuresExecQty2, futuresExecPrice2 float64
	var futuresStatus, futuresStatus2 futures.OrderStatusType
	var futuresErr, futuresErr2 error
	var bFuturesFilled = false
	if futuresLimitOrderId != 0 {
		_, futuresExecQty, futuresExecPrice, futuresStatus, futuresErr = getFuturesOrderInf(symbolPosition.Symbol, futuresLimitOrderId)
		if futuresStatus == futures.OrderStatusTypeFilled {
			bFuturesFilled = true
		} else {
			Warning.Printf("Futures Order %v status is %v, err is %v\n", futuresLimitOrderId, futuresStatus, futuresErr)
		}
	}
	if futuresAntiLimitOrderId != 0 {
		_, futuresExecQty2, futuresExecPrice2, futuresStatus2, futuresErr2 = getFuturesOrderInf(symbolPosition.Symbol, futuresAntiLimitOrderId)
		if futuresStatus2 == futures.OrderStatusTypeFilled {
			bFuturesFilled = true
		} else {
			Warning.Printf("Futures Order %v status is %v, err is %v\n", futuresAntiLimitOrderId, futuresStatus2, futuresErr2)
		}
	}
	if bFuturesFilled == false {
		return
	}

	if futuresLimitOrderId != 0 {
		err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}
	if futuresAntiLimitOrderId != 0 {
		err := cancelFuturesLimitOrder(canCreateSymbolBookTicker.Symbol, futuresAntiLimitOrderId)
		if err != nil {
			Error.Println(err)
		}
	}

	_, binanceExecQty, _, binanceStatus, _ := getBinanceOrderInf(symbolPosition.Symbol, binanceAntiLimitOrderId)
	err := cancelBinanceLimitOrder(symbolPosition.Symbol, binanceAntiLimitOrderId)
	if err != nil {
		Error.Println(err)
	}
	if binanceStatus == binance.OrderStatusTypeFilled || binanceStatus == binance.OrderStatusTypePartiallyFilled {
		err := createBinanceSellOrder(symbolPosition.Symbol, binanceExecQty)
		if err != nil {
			Error.Println(err)
		}
	}

	bFuturesOverBuy := false
	if futuresStatus == futures.OrderStatusTypeFilled {
		if futuresStatus2 == futures.OrderStatusTypeFilled || futuresStatus2 == futures.OrderStatusTypePartiallyFilled {
			bFuturesOverBuy = true
			futuresExecQty = futuresExecQty2
			futuresExecPrice = futuresExecPrice2
		}
	} else if futuresStatus2 == futures.OrderStatusTypeFilled {
		if futuresStatus == futures.OrderStatusTypeFilled {
			bFuturesOverBuy = true
		}
	}
	if bFuturesOverBuy {
		_, _, _, err := createFuturesSellOrder(symbolPosition.Symbol, futuresExecPrice, futuresExecQty)
		if err != nil {
			Error.Println(err)
		}
	}

	// 将状态转为非持仓状态
	err = ppersistence.DeleteArbitragePosition(symbolPosition.Symbol)
	if err != nil {
		Error.Println(err)
		panic(err)
	}

	err = stateMachine.ChangeState(State_NotPosition)
	if err != nil {
		Error.Println(err)
	}
	panic(err) // 测试
}

// 订单状态变更ws
func processWithExecutionReportEvent(event *binance.WsExecutionReportEvent) {
	Info.Println(stateMachine.State, *event)
	/*
		if stateMachine.State == State_LimitOrderCreated {
			if canCreateSymbolBookTicker.Symbol == event.Symbol && event.OrderStatus == binance.OrderStatusTypeFilled {
				Info.Println(*event)
				chanBinanceFilledOrder <- *event
			}
		} else if stateMachine.State == State_AntiLimitOrderCreated {
			if canCreateSymbolBookTicker.Symbol == event.Symbol && event.OrderStatus == binance.OrderStatusTypeFilled {
				Info.Println(*event)
				chanBinanceFilledOrder <- *event
			}
		}
	*/
	if canCreateSymbolBookTicker.Symbol == event.Symbol && event.OrderStatus == binance.OrderStatusTypeFilled {
		Info.Println(*event)
		select {
		case <-chanBinanceFilledOrder:
			chanBinanceFilledOrder <- *event
		default:
			chanBinanceFilledOrder <- *event
		}
	}
}

func processWithFuturesUserDataEvent(event *futures.WsUserDataEvent) {
	if event.Event != futures.UserDataEventTypeOrderTradeUpdate {
		return
	}
	orderTradeUpdate := event.OrderTradeUpdate
	Info.Println(stateMachine.State, orderTradeUpdate)
	/*
		if stateMachine.State == State_LimitOrderCreated {
			if canCreateSymbolBookTicker.Symbol == orderTradeUpdate.Symbol && orderTradeUpdate.Status == futures.OrderStatusTypeFilled {
				Info.Println(orderTradeUpdate)
				chanFuturesOrderTradeUpdate <- orderTradeUpdate
			}
		} else if stateMachine.State == State_AntiLimitOrderCreated {
			if canCreateSymbolBookTicker.Symbol == orderTradeUpdate.Symbol && orderTradeUpdate.Status == futures.OrderStatusTypeFilled {
				Info.Println(orderTradeUpdate)
				chanFuturesOrderTradeUpdate <- orderTradeUpdate
			}
		}
	*/
	if canCreateSymbolBookTicker.Symbol == orderTradeUpdate.Symbol && orderTradeUpdate.Status == futures.OrderStatusTypeFilled {
		Info.Println(orderTradeUpdate)
		select {
		case <-chanFuturesOrderTradeUpdate:
			chanFuturesOrderTradeUpdate <- orderTradeUpdate
		default:
			chanFuturesOrderTradeUpdate <- orderTradeUpdate
		}
	}
}

func main_v2() {
	wg := sync.WaitGroup{}
	wg.Add(1)
	go func() {
		defer wg.Done()
		processWithCurBookTicker()
	}()
	binance.WebsocketKeepalive = true
	var doneC, fdoneC, doneC2, fdoneC2 chan struct{}
	var err, ferr error
	var binanceWsAllBookTickerServe, futuresWsAllBookTickerServe, binanceWsUserDataServ, futuresWsUserDataServ func()
	binanceWsAllBookTickerServe = func() {
		doneC, _, err = binance.WsAllBookTickerServe(func(event *binance.WsBookTickerEvent) {
			if strings.Contains(event.Symbol, "USDT") {
				binanceBookTickerC <- event
			}
		}, func(e error) {
			Error.Println(e)
			if doneC != nil {
				doneC <- struct{}{}
			}
			if binanceWsAllBookTickerServe != nil {
				binanceWsAllBookTickerServe()
			}
		})
		if err != nil {
			Error.Printf("binance WsAllBookTickerServe error: %v\n", err)
			panic(err)
		}
	}
	futuresWsAllBookTickerServe = func() {
		fdoneC, _, ferr = futures.WsAllBookTickerServe(func(event *futures.WsBookTickerEvent) {
			if strings.Contains(event.Symbol, "USDT") {
				futuresBookTickerC <- event
			}
		}, func(e error) {
			Error.Println(e)
			if fdoneC != nil {
				fdoneC <- struct{}{}
			}
			if futuresWsAllBookTickerServe != nil {
				futuresWsAllBookTickerServe()
			}
		})
		if ferr != nil {
			Error.Printf("futures WsAllBookTickerServe error: %v\n", ferr)
			panic(ferr)
		}
	}
	binanceWsAllBookTickerServe()
	futuresWsAllBookTickerServe()

	listenerKey, err := clientPool.One().NewStartUserStreamService().Do(context.Background())
	if err != nil {
		Error.Println(err)
		panic(err)
	}

	flistenerKey, ferr := futuresClientPool.One().NewStartUserStreamService().Do(context.Background())
	if ferr != nil {
		Error.Println(ferr)
		panic(ferr)
	}

	defer func() {
		err = clientPool.One().NewCloseUserStreamService().ListenKey(listenerKey).Do(context.Background())
		ferr = futuresClientPool.One().NewCloseUserStreamService().ListenKey(flistenerKey).Do(context.Background())
		if err != nil {
			Error.Println(err)
		}
		if ferr != nil {
			Error.Println(ferr)
		}
	}()

	ticker := time.NewTicker(30 * time.Minute)
	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			<-ticker.C
			err = clientPool.One().NewKeepaliveUserStreamService().ListenKey(listenerKey).Do(context.Background())
			if err != nil {
				Error.Println(err)
				panic(err)
			}
			ferr = futuresClientPool.One().NewKeepaliveUserStreamService().ListenKey(flistenerKey).Do(context.Background())
			if ferr != nil {
				Error.Println(ferr)
				panic(ferr)
			}
		}
	}()

	binanceWsUserDataServ = func() {
		doneC2, _, err = binance.WsExecutionReportServe(listenerKey, processWithExecutionReportEvent, func(e error) {
			Error.Println(e)
			if doneC2 != nil {
				doneC2 <- struct{}{}
			}
			if binanceWsUserDataServ != nil {
				binanceWsUserDataServ()
			}
		})
		if err != nil {
			Error.Printf("binance WsExecutionReportServe error: %v\n", err)
			panic(err)
		}
	}

	futuresWsUserDataServ = func() {
		fdoneC2, _, ferr = futures.WsUserDataServe(flistenerKey, processWithFuturesUserDataEvent, func(e error) {
			Error.Println(e)
			if fdoneC2 != nil {
				fdoneC2 <- struct{}{}
			}
			if futuresWsUserDataServ != nil {
				futuresWsUserDataServ()
			}
		})
		if ferr != nil {
			Error.Printf("futures WsUserDataServe error: %v\n", ferr)
			panic(ferr)
		}
	}

	binanceWsUserDataServ()
	futuresWsUserDataServ()

	wg.Wait()
	doneC <- struct{}{}
	fdoneC <- struct{}{}
	doneC2 <- struct{}{}
	fdoneC2 <- struct{}{}
}
